package org.example.util;

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;

public class IO {
    public static int[] intArray(String str) {
        if (!str.contains(",")) {
            int[] ans = {};
            System.out.println("---Input Integer Array---");
            System.out.println(Arrays.toString(ans));

            return ans;
        }
        String trim = str.trim().replaceAll("\\[", "").replaceAll("]", "");
        String[] split = trim.split(",");
        int[] ans = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();

        System.out.println("---Input Integer Array---");
        System.out.println(Arrays.toString(ans));

        return ans;
    }

    public static ListNode intLinkedList(String str) {
        if (!str.contains(",")) {
            ListNode ans = new ListNode(-1, null);
            System.out.println("---Input LinkedList ---");
            System.out.println(ans);

            return ans;
        }

        String trim = str.trim().replaceAll("\\[", "").replaceAll("]", "");
        String[] split = trim.split(",");
        int[] intArray = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
        ListNode dummy = new ListNode(-1);
        ListNode head = dummy;
        for (Integer each : intArray) {
            ListNode node = new ListNode(each);
            dummy.next = node;
            dummy = node;
        }
        System.out.println("---Input Integer LinkedList---");
        StringBuilder sb = new StringBuilder();
        ListNode curr = head.next;
        while (curr != null) {
            sb.append(curr.val).append("->");
            curr = curr.next;
        }
        sb.delete(sb.length() - 2, sb.length());
        System.out.println(sb);

        return head.next;
    }

    public static String showLinedList(ListNode head) {
        ListNode curr = head;
        StringBuilder sb = new StringBuilder();

        while (curr != null) {
            sb.append(curr.val).append("->");
            curr = curr.next;
        }

        sb.delete(sb.length() - 2, sb.length());

        return sb.toString();
    }

    public TreeNode buildTreeByInorderAndPostOrder(int[] inorder, int[] postorder) {
        if (postorder == null || postorder.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(postorder[postorder.length - 1]);
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root);
        int inorderIndex = inorder.length - 1;
        for (int i = postorder.length - 2; i >= 0; i--) {
            int postorderVal = postorder[i];
            TreeNode node = stack.peek();
            if (node.val != inorder[inorderIndex]) {
                node.right = new TreeNode(postorderVal);
                stack.push(node.right);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex--;
                }
                node.left = new TreeNode(postorderVal);
                stack.push(node.left);
            }
        }
        return root;
    }
    public TreeNode buildTreeByPreorderAndInorder(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0) {
            return null;
        }

        TreeNode root = new TreeNode(preorder[0]);
        Deque<TreeNode> stack = new LinkedList<>();
        stack.push(root);
        int inorderIndex = 0;

        for (int i = 1; i < preorder.length; i++) {
            int preorderVal = preorder[i];
            TreeNode node = stack.peek();

            if (node.val != inorder[inorderIndex]) {
                node.left = new TreeNode(preorderVal);
                stack.push(node.left);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorderVal);
                stack.push(node.right);
            }
        }

        return root;
    }
}

